﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Zcu.PanelComposer.Views.UserControls
{
    /// <summary>
    /// Interaction logic for BaseCanvas.xaml
    /// </summary>
    public partial class BaseCanvas : UserControl
    {
        #region Fields

        private Polyline poly;
        private Polygon polygon;
        private Line line;
        private bool canMouseDown;
        private bool isSetUp = false;

        #endregion

        #region Dependency Property

        /// <summary>
        /// Gets or sets the poly collection.
        /// </summary>
        /// <value>
        /// The poly collection.
        /// </value>
        public PointCollection PolyCollection
        {
            get { return (PointCollection)GetValue(PolyCollectionProperty); }
            set { SetValue(PolyCollectionProperty, value); SetPolygon(); }
        }

        // Using a DependencyProperty as the backing store for PolyCollection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PolyCollectionProperty =
            DependencyProperty.Register("PolyCollection", typeof(PointCollection), typeof(BaseCanvas), new UIPropertyMetadata(null));

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseCanvas"/> class.
        /// </summary>
        public BaseCanvas()
        {
            InitializeComponent();

            Loaded += BaseCanvas_Loaded;
        }

        #endregion

        #region dp methods

        /// <summary>
        /// Handles the Changed event of the PolyCollection control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PolyCollection_Changed(object sender, EventArgs e)
        {
            SetPolygon();
        }

	    #endregion

        #region Event methods

        /// <summary>
        /// Handles the Loaded event of the BaseCanvas control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void BaseCanvas_Loaded(object sender, RoutedEventArgs e)
        {
            PolyCanvas.Children.Clear();
            poly = null;
            polygon = null;
            line = null;
            canMouseDown = true;
            this.Cursor = Cursors.Arrow;

            // pokud je kolekce nenulova, tak ji zobrazime
            if (PolyCollection != null)
            {
                PolyCollection.Changed += new EventHandler(PolyCollection_Changed);
                SetPolygon();
            }

            // vytvorime mrizku
            for (int i = 10; i < PolyBorder.Width; i += 10)
            {
                Line vertical = new Line();
                vertical.Stroke = Brushes.Silver;
                vertical.StrokeThickness = 0.1;
                vertical.X2 = vertical.X1 = i;
                vertical.Y1 = 0;
                vertical.Y2 = PolyBorder.Height;
                PolyCanvas.Children.Add(vertical);
            }

            for (int i = 10; i < PolyBorder.Height; i += 10)
            {
                Line horizontal = new Line();
                horizontal.Stroke = Brushes.Silver;
                horizontal.StrokeThickness = 0.1;
                horizontal.Y2 = horizontal.Y1 = i;
                horizontal.X1 = 0;
                horizontal.X2 = PolyBorder.Width;
                PolyCanvas.Children.Add(horizontal);
            }
        }

        #endregion

        #region Canvas methods

        /// <summary>
        /// Handles the MouseDown event of the PolyCanvas control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void PolyCanvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            // var point = e.GetPosition(PolyCanvas);
            var point = new Point((int)e.GetPosition(PolyCanvas).X, (int)e.GetPosition(PolyCanvas).Y);
            if (!canMouseDown) return;
            if (line == null)
            {
                line = new Line();
                line.Stroke = Brushes.Blue;
                line.StrokeThickness = 2.0;
                // pridano kvuli vystrelovani cary z 0,0 souradnice
                line.X2 = point.X;
                line.Y2 = point.Y;
                Canvas.SetZIndex(line, 2);

                PolyCanvas.Children.Add(line);
            }

            line.X1 = point.X;
            line.Y1 = point.Y;

            if (poly == null)
            {
                poly = new Polyline();
                Canvas.SetZIndex(poly, 1);
                poly.Stroke = Brushes.Blue;
                poly.Fill = Brushes.LightBlue;
                poly.StrokeThickness = 2.0;
                poly.Points.Add(point);
                PolyCanvas.Children.Add(poly);
            }
            else
            {
                if (e.RightButton == MouseButtonState.Pressed)
                {
                    PolyCanvas.Children.Remove(poly);
                    PolyCollection = poly.Points;
                    SetPolygon();
                }
                else
                {
                    poly.Points.Add(point);
                }
            }
        }

        /// <summary>
        /// Handles the MouseMove event of the PolyCanvas control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseEventArgs"/> instance containing the event data.</param>
        private void PolyCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            var point = new Point((int)e.GetPosition(PolyCanvas).X, (int)e.GetPosition(PolyCanvas).Y);
            PointsBlock.Text = point.ToString();

            string polygonString = string.Empty;
            if (poly != null && poly.Points.Count > 0)
            {
                polygonString = string.Format(" ({0})", poly.Points.ToString());
            }
            else if (polygon != null)
            {
                polygonString  = string.Format(" ({0})", polygon.Points.ToString());
            }
            PointsBlock.Text += polygonString;

            if (line != null)
            {
                line.X2 = point.X;
                line.Y2 = point.Y;
                line.Stroke = Brushes.Blue;
                line.StrokeDashArray = null;
                this.Cursor = Cursors.Arrow;
                canMouseDown = true;

                Point last = new Point();
                bool isFirst = true;
                Point line1 = new Point(line.X1, line.Y1);
                foreach (Point p in poly.Points)
                {
                    if (!isFirst)
                    {
                        Point intersect;
                        if (ClippingEar.LineIntersect(last, p, line1, point, out intersect))
                        {
                            if (intersect != p && intersect != last && intersect != line1 && intersect != point)
                            {
                                line.Stroke = Brushes.Red;
                                line.StrokeDashArray = DoubleCollection.Parse("4 4");
                                this.Cursor = Cursors.No;
                                canMouseDown = false;
                            }
                        }
                    }
                    else
                    {
                        isFirst = false;
                    }
                    last = p;
                }
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Sets the polygon.
        /// </summary>
        private void SetPolygon()
        {
            PolyCanvas.Children.Remove(poly);
            PolyCanvas.Children.Remove(polygon);
            PolyCanvas.Children.Remove(line);

            this.Cursor = Cursors.Arrow;
            canMouseDown = true;
            poly = null;
            polygon = null;
            line = null;

            // pokud je kolekce nenulova, tak ji zobrazime
            if (PolyCollection != null)
            {
                polygon = new Polygon();
                polygon.Stroke = Brushes.Blue;
                polygon.Fill = Brushes.LightBlue;
                polygon.StrokeThickness = 2.0;
                polygon.Points = PolyCollection;

                PolyCanvas.Children.Add(polygon);
            }
        }

        #endregion
    }
}
